<!doctype html>
<html>
<head>
  <title>Google Wallet for Digital Payments</title>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="chrome=1">
  <!--<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">-->
  <!--<meta name="viewport" content="width=device-width, initial-scale=1.0">-->
  <!--This one seems to work all the time, but really small on ipad-->
  <!--<meta name="viewport" content="initial-scale=0.4">-->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <link rel="stylesheet" media="all" href="theme/css/default.css">
  <link rel="stylesheet" media="only screen and (max-device-width: 480px)" href="theme/css/phone.css">
  <base target="_blank"> <!-- This amazingness opens all links in a new tab. -->
  <script data-main="js/slides" src="js/require-1.0.8.min.js"></script>
</head>

<body style="opacity: 0">

<slides class="layout-widescreen">
  <slide class="logoslide nobackground">
    <article class="flexbox vcenter">
      <span><img src="images/google_developers_logo.png"></span>
    </article>
  </slide>

  <slide class="title-slide segue nobackground">
    <aside class="gdbar"><img src="images/google_developers_icon_128.png"></aside>
    <!-- The content of this hgroup is replaced programmatically through the slide_config.json. -->
    <hgroup class="auto-fadein">
      <h1 data-config-title><!-- populated from slide_config.json --></h1>
      <h2 data-config-subtitle><!-- populated from slide_config.json --></h2>
      <p data-config-presenter><!-- populated from slide_config.json --></p>
    </hgroup>
  </slide>
  
  <slide>
    <h2>Agenda</h2>
    <br />
    <ul class="build fade">
      <li>Setting Up</li>
      <li>Basic Purchase Page</li>
      <li>Merchant Center Introduction</li>
      <li>JWT Generation</li>
      <li>Postback Handling</li>
      <li>Tying It All Together</li>
    </ul>
  </slide>
  
  <slide class="fill nobackground" style="background-image: url(images/foundation.jpg)">
    <aside class="bgbar">
      <h2 class="right">Setting up</h2>
    </aside>
  </slide>
  
  <slide>
    <h2>Git Repo</h2>
    <p>git clone https://code.google.com/p/google-wallet-io12-codelab/</p>
  </slide>
  
  <slide>
    <h2>Wallet Accounts</h2>
    <h3><ul>
      <li>Merchant Account - http://goo.gl/4N11S</li>
      <li>Buyer Account - http://goo.gl/3XE2R</li>
    </ul></h3>
  </slide>
  
  <slide>
    <h2>Appengine Account</h2>
    <ul>
      <li>Appengine account - http://appspot.com</li>
      <li>Java Plugin for Eclipse- http://goo.gl/hBFBL </li>
      <li>Java SDK - http://goo.gl/Hv02a</li>
      <li>Python SDK - http://goo.gl/cXZT8</li>
    </ul>
  </slide>
  
  <slide class="fill nobackground" style="background-image: url(images/trainingwheels.jpg)">
    <aside class="bgbar">
      <h2 class="right">Basic Buy Page</h2>
    </aside>
  </slide>
  
  <slide>
    <h2>Include Javascript</h2>
<pre class="prettyprint" data-lang="javascript">
&lt;script type=&quot;text/javascript&quot; src=&quot;https://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
  google.load(&#x27;payments&#x27;, &#x27;1.0&#x27;, {
    &#x27;packages&#x27;: [&#x27;sandbox_config&#x27;]
  });
&lt;/script&gt;
</pre>
  </slide>
  
  <slide>
    <h2>Handle Click Action</h2>
    <pre class="prettyprint" data-lang="javascript">
&lt;script type=&quot;text/javascript&quot;&gt;
function buy() {
  goog.payments.inapp.buy({
    parameters: {},
    jwt: &quot;eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxNDIwNDk&quot; +
&quot;1MzA5NDM1MjE2ODU3MSIsImF1ZCI6Ikdvb2dsZSI&quot; +
&quot;sInR5cCI6Imdvb2dsZS9wYXltZW50cy9pbmFwcC9&quot; +
&quot;pdGVtL3YxIiwiaWF0IjoxMzM4NjExMjc5LCJleHA&quot; +
&quot;iOjEzMzk2MDAwMDAsInJlcXVlc3QiOnsibmFtZSI&quot; +
&quot;6IlBpZWNlIG9mIENha2UiLCJkZXNjcmlwdGlvbiI&quot; +
&quot;6IkEgZGVsaWNpb3VzIHBpZWNlIG9mIHZpcnR1YWw&quot; +
&quot;gY2FrZSIsInByaWNlIjoiMTAuNTAiLCJjdXJyZW5&quot; +
&quot;jeUNvZGUiOiJVU0QiLCJzZWxsZXJEYXRhIjoiWW9&quot; +
&quot;1ciBEYXRhIEhlcmUifX0.97lNxDriGQIPtqoS3ue&quot; +
&quot;dGwKrcMF40wqINhM8nQkIzMg&quot;,
    success: function() {window.alert(&quot;success&quot;)},
    failure: function() {window.alert(&quot;failure&quot;)}
  });
}
&lt;/script&gt;
    </pre>
  </slide>
  
  <slide>
    <h2>Buy Button</h2>
    <pre class="prettyprint" data-lang="javascript">
&lt;!--- place button in the appropriate place on your page--&gt;
&lt;button onclick=&quot;buy();&quot; id=&quot;runDemoButton&quot; value=&quot;buy&quot;&gt;&lt;b&gt;Purchase&lt;/b&gt;&lt;/button&gt;
    </pre>
    <button onclick="buy();" id="runDemoButton" value="buy"><b>Purchase</b></button>
  </slide>
  
  
  <slide class="fill nobackground" style="background-image: url(images/ikea.jpg)">
    <aside class="bgbar">
      <h2 class="right">Merchant Center</h2>
    </aside>
  </slide>
  
  <slide>
    <hgroup>
      <h2>Merchant Center</h2>
    </hgroup>
    <article class="flexbox vcenter">
      <a href="https://checkout.google.com/sell">https://checkout.google.com/sell</a>
      <img src="images/checkoutmerchantcenter.gif" class="reflect"> 
    </article>
  </slide>
  
  <slide class="fill nobackground" style="background-image: url(images/package.jpg)">
    <aside class="bgbar">
      <h2 class="right">JWT Generation</h2>
    </aside>
  </slide>
  
  <slide>
    <hgroup>
      <h2>Libraries</h2>
    </hgroup>
    <article>
      <ul>
        <li>Java Library - http://code.google.com/p/jsontoken/</li>
        <li>Python Library - https://github.com/progrium/pyjwt</li>
        <li>Other Langauges - https://developers.google.com/in-app-payments/docs/libraries</li>
      </ul>
    </article>
  </slide>
  
  <slide>
    <hgroup>
      <h2>JWT Format</h2>
    </hgroup>
    <article>
      Base64 encoded data<br />
      header.body.signature<br />
      JWT decoder - https://developers.google.com/in-app-payments/docs/jwtdecoder<br />
      atob("eyJhdWQiOiAiR29vZ2xlIiwgImlzcyI6ICIxMDg3MzY2MDM1NDYyMDA5NDcxNiIsICJyZXF1ZXN0IjogeyJwcmljZSI6ICI5Ljk5IiwgImN1cnJlbmN5Q29kZSI6ICJVU0QiLCAic2VsbGVyRGF0YSI6ICIrZ29sZCwgK25vL2NvdXBvbi9kaXNjb3VudCIsICJuYW1lIjogIlZpcnR1YWwgR29sZCBNZWRhbCIsICJkZXNjcmlwdGlvbiI6ICJBIHZpcnR1YWwgZ29sZCBtZWRhbCBmcm9tIHRoZSAyMDEwIG9seW1waWMgZ2FtZXMgZm9yIG1lbidzIGZyZWVzdHlsZSBza2lpbmcuIn0sICJleHAiOiAxMzEyMjM5OTY1LCAiaWF0IjogMTMxMjIzOTM2NSwgInR5cCI6ICJnb29nbGUvcGF5bWVudHMvaW5hcHAvaXRlbS92MSJ9");
    </article>
  </slide>
  
  <slide>
    <hgroup>
      <h2>Eclipse Appengine Project Step 1</h2>
    </hgroup>
    <article>
      Create New Web App Project<br />
      <img src="images/appenginestep1.png"> <br />
      Uncheck Use Google Web Toolkit
    </article>
  </slide>
  
  <slide>
    <hgroup>
      <h2>Eclipse Appengine Project Step 2</h2>
    </hgroup>
    <article>
      Insert your application name in war/WEB-INF/appengine-web.xml
    </article>
    <pre class="prettyprint" data-lang="xml">
&lt;appengine-web-app xmlns=&quot;http://appengine.google.com/ns/1.0&quot;&gt;
  &lt;application&gt;&lt;/application&gt;
  &lt;version&gt;1&lt;/version&gt;
    </pre>
    <article>
      Run application
    </article>
  </slide>
  
  <slide>
    <hgroup>
      <h2>Eclipse Appengine Project Step 3</h2>
    </hgroup>
    <article>
      Add Id & Secret to web.xml<br />
    </article>
    <pre class="prettyprint" data-lang="xml">
&lt;context-param&gt;
	&lt;param-name&gt;sellerId&lt;/param-name&gt;
	&lt;param-value&gt;[SellerId]&lt;/param-value&gt;
&lt;/context-param&gt;

&lt;context-param&gt;
	&lt;param-name&gt;sellerSecret&lt;/param-name&gt;
	&lt;param-value&gt;[SellerSecret]&lt;/param-value&gt;
&lt;/context-param&gt;
    </pre>
  </slide>
  
  <slide>
    <hgroup>
      <h2>Eclipse Appengine Project Step 4</h2>
    </hgroup>
    <article>
      Create or update servlet<br />
    </article>
    <pre class="prettyprint" data-lang="java">
public void doPost(HttpServletRequest req, HttpServletResponse resp)
     throws IOException {
   String sellerId = getServletContext().getInitParameter(&quot;sellerId&quot;);
   String sellerSecret = getServletContext().getInitParameter(&quot;sellerSecret&quot;);
   Request request = new Request(&quot;Item Name&quot;,
       &quot;Item Description&quot;,
       &quot;10.00&quot;,
       &quot;USD&quot;,
       &quot;Seller Data&quot;);
   InAppJWT iap = new InAppJWT(request);
   IapService iapService = new IapService(sellerId, sellerSecret);
   String iapJWT = iapService.jwtToString(iap);
   resp.setContentType(&quot;text/plain&quot;);
   resp.getWriter().println(iapJWT);
}
    </pre>
  </slide>

  <slide>
    <hgroup>
      <h2>Eclipse Appengine Project Step 5</h2>
    </hgroup>
    <article>
      Request Server Generated JWT<br />
    </article>
    <pre class="prettyprint" data-lang="javascript">
&lt;script type=&quot;text/javascript&quot;
  src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js&quot;&gt;&lt;/script&gt;
var success = function(data){
  goog.payments.inapp.buy({
      parameters: {,
      jwt: data,
      success: function(success) {console.log(success);  window.alert(&quot;success&quot;)},
      failure: function(error) {console.log(error); window.alert(&quot;failure&quot;)}
    });
    return false;
  };
}
function buy(){
  $.post(&quot;iap&quot;, success);
}
    </pre>
  </slide>
   <slide>
    <hgroup>
      <h2>Eclipse Appengine Project Step 6</h2>
    </hgroup>
    <article>
      Debug and deploy to Appengine<br />
      <img src="images/deploy.png" class="reflect"> <br />
    </article>
  </slide>
  
  <slide>
    <hgroup>
      <h2>TODO: See if we can add subscriptions</h2>
    </hgroup>
  </slide>
  
  <slide class="fill nobackground" style="background-image: url(images/network.jpg)">
    <aside class="bgbar">
      <h2 class="right">Postback Handling</h2>
    </aside>
  </slide>
  
  <slide>
    <hgroup>
      <h2>Create new postback handler servlet</h2>
    </hgroup>
    <article>
      Create or update servlet<br />
    </article>
    <pre class="prettyprint" data-lang="java">
String jwt = req.getParameter("jwt");
IapService iapService = 
  new IapService(getServletContext().getInitParameter("sellerId"),
  getServletContext().getInitParameter("sellerSecret"));

InAppJWT iapJwt = iapService.stringToJwt(jwt);

try {
  PrintWriter out = resp.getWriter();
  out.print(iapJwt.getResponse().getOrderId());
  out.flush();
  out.close();
} catch (IOException e) {
  e.printStackTrace();
}
    </pre>
  </slide>
  
  <slide>
    <hgroup>
      <h2>Update your postback URL</h2>
    </hgroup>
    <article>
      Login at http://goo.gl/4N11S<br />
      Enter your post back as http://[application name].appspot.com/[handler path]
      <img src="images/iapmc.png" class="reflect"> 
    </article>
  </slide>
  
  <slide class="fill nobackground" style="background-image: url(images/deathstar.jpg)">
    <aside class="bgbar">
      <h2 class="right">Putting It Together</h2>
    </aside>
  </slide>
  
  <slide>
    <hgroup>
      <h2>TODO: Fill out sample site info</h2>
    </hgroup>
  </slide>
  
  <slide class="thank-you-slide segue nobackground">
    <aside class="gdbar right"><img src="images/google_developers_icon_128.png"></aside>
    <article class="flexbox vleft auto-fadein">
      <h2>Thank You!</h2>
    </article>
    <p class="auto-fadein" data-config-contact>
      <!-- populated from slide_config.json -->
    </p>
  </slide>

  <slide class="logoslide dark nobackground">
    <article class="flexbox vcenter">
      <span><img src="images/google_developers_logo_white.png"></span>
    </article>
  </slide>
               
  <slide class="backdrop"></slide>
  </slide>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
  google.load('payments', '1.0', {
    'packages': ['sandbox_config']
  });
  function buy() {
      goog.payments.inapp.buy({
        parameters: {},
        jwt: "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxNDIwNDk" +
"1MzA5NDM1MjE2ODU3MSIsImF1ZCI6Ikdvb2dsZSI" +
"sInR5cCI6Imdvb2dsZS9wYXltZW50cy9pbmFwcC9" +
"pdGVtL3YxIiwiaWF0IjoxMzM4NjExMjc5LCJleHA" +
"iOjEzMzk2MDAwMDAsInJlcXVlc3QiOnsibmFtZSI" +
"6IlBpZWNlIG9mIENha2UiLCJkZXNjcmlwdGlvbiI" +
"6IkEgZGVsaWNpb3VzIHBpZWNlIG9mIHZpcnR1YWw" +
"gY2FrZSIsInByaWNlIjoiMTAuNTAiLCJjdXJyZW5" +
"jeUNvZGUiOiJVU0QiLCJzZWxsZXJEYXRhIjoiWW9" +
"1ciBEYXRhIEhlcmUifX0.97lNxDriGQIPtqoS3ue" +
"dGwKrcMF40wqINhM8nQkIzMg",
        success: function() {window.alert("success")},
        failure: function() {window.alert("failure")}
      });
  }
</script>
</slides>
</body>